<?php
/**
 * Created by PhpStorm.
 * User: lixy
 * Date: 2016/3/3
 * Time: 16:22
 */

namespace app\lib;

use Yii;

class Mch_pay
{
    /**
     *
     * 产生随机字符串，不长于32位
     * @param int $length
     * @return 产生的随机字符串
     */
    public static function getNonceStr($length = 32)
    {
        $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
        $str = "";
        for ($i = 0; $i < $length; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }

    /**
     * 获取毫秒级别的时间戳
     */
    private static function getMillisecond()
    {
        //获取毫秒的时间戳
        $time = explode(" ", microtime());
        $time = $time[1] . ($time[0] * 1000);
        $time2 = explode(".", $time);
        $time = $time2[0];
        return $time;
    }

    /**
     * 以post方式提交xml到对应的接口url
     *
     * @param string $xml 需要post的xml数据
     * @param string $url url
     * @param bool $useCert 是否需要证书，默认不需要
     * @param int $second url执行超时时间，默认30s
     * @throws WxPayException
     */
    private static function postXmlCurl($xml, $url, $useCert = false, $second = 30)
    {




        $ch = curl_init();
        //设置超时
        curl_setopt($ch, CURLOPT_TIMEOUT, $second);


        curl_setopt($ch, CURLOPT_URL, $url);

        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);//严格校验
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        //设置header
        curl_setopt($ch, CURLOPT_HEADER, FALSE);
        //要求结果为字符串且输出到屏幕上
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);

        if ($useCert == true) {
            //设置证书
            //使用证书：cert 与 key 分别属于两个.pem文件
            curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM');
            curl_setopt($ch, CURLOPT_SSLCERT, Yii::$app->params['SSLCERT_PATH']);
            curl_setopt($ch, CURLOPT_SSLKEYTYPE, 'PEM');
            curl_setopt($ch, CURLOPT_SSLKEY, Yii::$app->params['SSLKEY_PATH']);
        }
        //post提交方式
        curl_setopt($ch, CURLOPT_POST, TRUE);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
        //运行curl
        $data = curl_exec($ch);
        //返回结果
        if ($data) {
            curl_close($ch);
            return $data;
        } else {
            $error = curl_errno($ch);
            curl_close($ch);
            throw new \Exception("curl出错，错误码:$error");
        }
    }

    /**
     * 格式化参数格式化成url参数
     */
    public static function ToUrlParams($values = [])
    {
        $buff = "";
        foreach ($values as $k => $v) {
            if ($k != "sign" && $v != "" && !is_array($v)) {
                $buff .= $k . "=" . $v . "&";
            }
        }

        $buff = trim($buff, "&");
        return $buff;
    }

    /**
     * 生成签名
     * @return 签名，本函数不覆盖sign成员变量，如要设置签名需要调用SetSign方法赋值
     */
    public function MakeSign($values = [])
    {
        //签名步骤一：按字典序排序参数
        ksort($values);
        $string = static::ToUrlParams($values);

        //签名步骤二：在string后加入KEY
        $string = $string . "&key=" . PAYKEY;
        //签名步骤三：MD5加密
        $string = md5($string);
        //签名步骤四：所有字符转为大写
        $result = strtoupper($string);
        return $result;
    }
    /* public function SetSign()
     {
         $sign = $this->MakeSign();
         $this->values['sign'] = $sign;
         return $sign;
     }*/
    /**
     * 输出xml字符
     * @throws WxPayException
     **/
    public static function ToXml($values = [], $isCDATA = false)
    {
        if (!is_array($values)
            || count($values) <= 0
        ) {
            throw new \Exception("数组数据异常！");
        }

        $xml = "<xml>";
        foreach ($values as $key => $val) {
            if (is_numeric($val)) {
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
            } else {
                if ($isCDATA) {
                    $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
                } else {
                    $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
                }


            }
        }
        $xml .= "</xml>";
        return $xml;
    }

    const transfers_url = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers';

    public static function test()
    {
        ini_set('display_errors', 1);
        try {
            $values = [];
            $values['mch_appid'] = APPID;
            $values['mchid'] = MCHID;
            $values['nonce_str'] = static::getNonceStr();
            //商户订单号
            $values['partner_trade_no'] = 'test_' . static::getMillisecond();
            $values['openid'] = 'ozSzqwoHxdTrhrSQ5HvAzSZ2Fnqc';
            $values['check_name'] = 'NO_CHECK';
//        $values['re_user_name']='李小毅';

            $values['amount'] = 1*100;
            $values['desc'] = '测试企业支付2';

            $values['spbill_create_ip'] = '182.254.216.240';


            $sign = static::MakeSign($values);
            $values['sign'] = $sign;
            $xmlInfo = static::ToXml($values);
            echo $xmlInfo;

            $re = static::postXmlCurl($xmlInfo, static::transfers_url, true);
            echo $re;
        } catch (\Exception $e) {
            echo $e->getMessage();
        }
        exit;
    }
}